#include "xPlugManager.h"
#include "xLogManager.h"
#include "XEngine.h"
#include <io.h>


#define  CreatePlugFunName "CreatexEnginePlug"
#define  DeletePlugFunName "ReleasexEnginePlug"

namespace XE	
{

	extern "C"
	{
		typedef  xPlug*(*_CreatePlug)();
		typedef  void(*_DeletePlug)(xPlug*);

		//typedef HRESULT(*CREATEDEVICE)(HINSTANCE instan,XRenderSystem** device);
		//typedef HRESULT(*RELEASEDEVICE)(XRenderSystem* device);
	}



	

	xPlugManager* Singleton<xPlugManager>::ms_Singleton = NULL;

	xPlugManager::xPlugManager()
    {

	    Init();

	}

	//-------load PlugFile all dll
	void xPlugManager:: Init()
	{
		const xEngineConfig& config = XEngine::getSingleton().GetConfig();
		const xStringMap& plugMap =config.GetPlugList();

		xStringMap::const_iterator it = plugMap.begin();
		for(;it!=plugMap.end();++it)
		{

			xString PlugFileName = it->second;
#ifdef _DEBUG
			PlugFileName+="_d.dll";
#else	
			PlugFileName+=".dll";
#endif

			if(_access(PlugFileName.c_str(),0)==0)
			{
			
				HMODULE module =    LoadLibraryA(PlugFileName.c_str());
				if(module==NULL)
				{
					xLogMessager::getSingleton().logMessage("Load Plug Fail Err lib name is:"+it->first);
					 continue;
				}

				_CreatePlug CreatePlugFun = (_CreatePlug) GetProcAddress(module,CreatePlugFunName);
				_DeletePlug DeletePlugFnu = (_DeletePlug) GetProcAddress(module,DeletePlugFunName);

				if(CreatePlugFun==NULL||DeletePlugFnu==NULL)
				{
					xLogMessager::getSingleton().logMessage\
						("Load Plug Fail cant find the CreatePlugFun or deletePlugfun:"+it->first);
					 continue;
				}

				xPlug* pTemPlug = CreatePlugFun();
				if(pTemPlug==NULL)
				{
                  xLogMessager::getSingleton().logMessage("Create plug ,lib name is"+it->first);
				  continue;
				}
				pTemPlug->SetModule(module);
				if(pTemPlug!=NULL)
				{
					if(InstallPlug(pTemPlug)==false)
					{
						DeletePlugFnu(pTemPlug);
						pTemPlug=NULL;
						FreeLibrary(module);
						continue;
					}else
					{
						xLogMessager::getSingleton().logMessage("Install plug Succeed,lib name is"+it->first);
					}

				}






			}

		}



	}


	bool xPlugManager::InstallPlug(xPlug* pPlug)
	{
		if(pPlug==NULL)
			return false;
		if(FindPlug(pPlug->GetName())!=NULL)
		{
			xLogMessager::getSingleton().logMessage\
				("install plug fail ,there has same name plug name is:"+pPlug->GetName());
             return false;
		}

		if(pPlug->InstallPlug()==false)
		{
			xLogMessager::getSingleton().logMessage("Install plug Fail.InstatllPlug Is fail name is"+pPlug->GetName());
		}
		m_PlugVector.push_back(pPlug);
		return true;

	}



	void xPlugManager::UnInstallAllPlug()
	{
		PlugVector::iterator it = m_PlugVector.begin();	
		
		for(;it!=m_PlugVector.end();++it)
		{
			xString PlugName = (*it)->GetName();
			if((*it)->UnInstallPlug()==false)
			{
				xLogMessager::getSingleton().logMessage("UnInstall Plug is err,name is: "+PlugName);
			}
			HMODULE module = (*it)->GetModule();
			_DeletePlug DeleteFun = (_DeletePlug)GetProcAddress(module,DeletePlugFunName);
			if(DeleteFun!=NULL)
			{
				DeleteFun(*it);
			}else
			{
				xLogMessager::getSingleton().logMessage("Uninstall plug is err,can't find delete fun");
			}
			if(FreeLibrary(module))
			{
				xLogMessager::getSingleton().logMessage("Uninstall plug succeed,lib is: "+PlugName);
			}
		}
		m_PlugVector.clear();
		return ;

	}

	bool xPlugManager::unInstallPlug(const xString& PlugName)
	{

		PlugVector::iterator it = m_PlugVector.begin();
		for(;it!=m_PlugVector.end();++it)
		{
			if((*it)->GetName()==PlugName)
			{

				if((*it)->UnInstallPlug()==false)
				{
					xLogMessager::getSingleton().logMessage("UnInstall Plug is Fail,name is"+PlugName);
					//return false;
				}
                 HMODULE module = (*it)->GetModule();
				_DeletePlug DeleteFun = (_DeletePlug)GetProcAddress(module,DeletePlugFunName);
				if(DeleteFun!=NULL)
				{
				    DeleteFun(*it);
				}else
				{
					xLogMessager::getSingleton().logMessage("Uninstall plug is err,can't find delete fun");
				}
				 if(FreeLibrary(module))
				 {
					 xLogMessager::getSingleton().logMessage("Uninstall plug succeed,lib is"+(*it)->GetName());
				 }
				m_PlugVector.erase(it);
				return true;
			}
		}
		
		return false;

	}

	xPlug* xPlugManager::FindPlug(const xString& name)
	{

		PlugVector::iterator it = m_PlugVector.begin();
		for(;it!=m_PlugVector.end();++it)
		{
			if((*it)->GetName()==name)
			{
				return *it;
			}

		}

		return NULL;

	}


	size_t xPlugManager::GetPlugCount(UINT index)
	{

		return m_PlugVector.size();
	}

	xPlug* xPlugManager::GetPlugByIndex(UINT index)
	{
		if(index<m_PlugVector.size()-1)
		{

			return m_PlugVector.at(index);
		}else
		{
			return NULL;
		}

	}




}